#include <jni.h>
#include <string>

#include "spdlog/include/spdlog/spdlog.h"
#include "spdlog/sinks/android_sink.h"
#include "SLog.h"
#include "SeperatorTool.h"
#include "FFSeperator.h"
#include "JavaCallHelper.h"
#include <SafeQueue.h>
extern "C" {
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavcodec/jni.h"
}
#include "FavFrameHelper.h"
#include "LogUtil.h"
#include "JavaCallHelper.h"
#include <VideoGLRender.h>
FFStatus *ffStatus;
FavFrameHelper *favFrameHelper;
JavaVM *javaVm;


JavaCallHelper *helper;
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
    jint result = -1;
    javaVm = vm;
    JNIEnv *env;
    //mediacode ffmepg sets environment
    av_jni_set_java_vm(vm, NULL);
    if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
        LOGCATE("ERROR: GetEnv failed\n");
        return result;
    }
    return JNI_VERSION_1_6;

}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_shen_show_NativeLib_00024Companion_stringFromJNI(JNIEnv *env, jobject thiz) {
// TODO: implement stringFromJNI()
    std::string hello = "Hello from C++ 23";
    SLog::GetInstance()->getLogger()->debug("4343");
    std::stringstream version_info;
    version_info << "libavutil version "
                 << AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO)
                 << std::endl;
//  类似方法获取libavcodec和libavformat版本
//  version_info.str()
    char strBuffer[1024 * 4] = {0};
    strcat(strBuffer, "libavcodec : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVCODEC_VERSION));
    strcat(strBuffer, "\nlibavformat : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVFORMAT_VERSION));
    strcat(strBuffer, "\nlibavutil : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVUTIL_VERSION));
    strcat(strBuffer, "\nlibavfilter : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVFILTER_VERSION));
    strcat(strBuffer, "\nlibswresample : ");
    strcat(strBuffer, AV_STRINGIFY(LIBSWRESAMPLE_VERSION));
    strcat(strBuffer, "\nlibswscale : ");
    strcat(strBuffer, AV_STRINGIFY(LIBSWSCALE_VERSION));
    strcat(strBuffer, "\navcodec_configure : \n");
    strcat(strBuffer, avcodec_configuration());
    strcat(strBuffer, "\navcodec_license : ");
    strcat(strBuffer, avcodec_license());
    MESSAGEI("GetFFmpegVersion\n%s", strBuffer);
    MESSAGEI("version_info %s",strBuffer);
    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_00024Companion_onSurfaceCreated(JNIEnv *env, jobject thiz) {
    VideoGLRender::GetInstance()->onSurfaceCreated();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_00024Companion_onSurfaceChanged(JNIEnv *env, jobject thiz, jint width,
                                                             jint height) {
    VideoGLRender::GetInstance()->onSurfaceChanged(width,height);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_00024Companion_onDrawFrame(JNIEnv *env, jobject thiz) {
    VideoGLRender::GetInstance()->onDrawFrame();
}



extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_init_1frame_1by_1ffmpeg(JNIEnv *env, jobject thiz, jstring source) {

    if (helper== nullptr){
        helper=new JavaCallHelper(javaVm,env,thiz);
    }

    if (ffStatus== nullptr){
        ffStatus=new FFStatus();
    }
    if (favFrameHelper==nullptr){
        const char* url = env->GetStringUTFChars(source,0);
        favFrameHelper=new FavFrameHelper(helper,url,ffStatus);
    }

   favFrameHelper->init();

}
extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_get_1each_1frame(JNIEnv *env, jobject thiz) {
//    if (seperatorTool!= nullptr) {
//        seperatorTool->getFrame();
//    }
}

extern "C"
JNIEXPORT jlong JNICALL
Java_com_shen_show_NativeLib_n_1prepare(JNIEnv *env, jobject thiz, jstring path) {

    const char *vpath=env->GetStringUTFChars(path, nullptr);
    if (helper == nullptr) {
            helper = new JavaCallHelper(javaVm, env, thiz);
    }
    if (ffStatus == nullptr) {
        ffStatus = new FFStatus();
    }

    auto seperatorTool = new FFSeperator(vpath, ffStatus, helper);
    seperatorTool->prepare();

    env->ReleaseStringUTFChars(path,vpath);
    return reinterpret_cast<jlong>(seperatorTool);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_n_1start(JNIEnv *env, jobject thiz,jlong player) {
    auto *ffSeperator=reinterpret_cast<FFSeperator*>(player);
    ffSeperator->start();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_shen_show_NativeLib_n_1start_1by_1ffmpeg(JNIEnv *env, jobject thiz) {
    if (favFrameHelper!= nullptr)
    favFrameHelper->startAvFrame();
}